﻿using MyWPF.StaticData;
using MyWPF.Views.Others;
using NPOI.OpenXmlFormats.Spreadsheet;
using OPCAutomation;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;

namespace MyWPF.ViewModel.Setting
{
    public class VM_SetWindow_OPC : BaseViewModel
    {
        public VM_SetWindow_OPC() 
        {
            #region 事件委托
            _refreshOPC = new DelegateCommand<object>(_RefreshOPC);
            #endregion
        }

        private void OnPropertyChanged(string v)
        {
            throw new NotImplementedException();
        }

        #region 属性绑定：下拉框绑定
        /// <summary>
        /// OPC开关
        /// </summary>
        public bool OpcSwitch
        {
            get { return _opcSwitch; }
            set 
            { 
                SetProperty(ref _opcSwitch, value); 
                switch(value)
                {
                    case true:
                        LinkOPC();
                        break;
                    case false:
                        CloseOPC();
                        break;
                }
            }
        }
        private bool _opcSwitch;
        /// <summary>
        /// 所有OPC节点
        /// </summary>
        public ObservableCollection<string> OpcSource
        {
            get { return _opcSource; }
            set { SetProperty(ref _opcSource, value); }
        }
        private ObservableCollection<string> _opcSource;
        /// <summary>
        /// 用户选择的OPC节点
        /// </summary>
        public string OpcSelected
        {
            get { return _opcSelected; }
            set 
            { 
                SetProperty(ref _opcSelected, value); 
                if (value != null && value != "")
                {
                    GetOpcNameList();
                }
            }
        }
        private string _opcSelected;
        /// <summary>
        /// 所有OPC名称
        /// </summary>
        public ObservableCollection<string> OpcName
        {
            get { return _opcName; }
            set { SetProperty(ref _opcName, value); }
        }
        private ObservableCollection<string> _opcName;
        /// <summary>
        /// 用户选择的OPC名称
        /// </summary>
        public string NameSelected
        {
            get { return _nameSelected; }
            set { SetProperty(ref _nameSelected, value); }
        }
        private string _nameSelected;
        /// <summary>
        /// 变量列表
        /// </summary>
        public ObservableCollection<string> Variable
        {
            get { return _variable; }
            set { SetProperty(ref _variable, value); }
        }
        private ObservableCollection<string> _variable;
        /// <summary>
        /// 用户选择的变量
        /// </summary>
        public string VariableSelected
        {
            get { return _variableSelected; }
            set 
            { 
                SetProperty(ref _variableSelected, value);
                VariableValue = GetOpcData(value);
            }
        }
        private string _variableSelected;
        #endregion

        #region 属性绑定：OPC相关属性：OPC URL
        /// <summary>
        /// OPC URL
        /// </summary>
        public string OpcUrl
        {
            get { return _opcUrl; }
            set { SetProperty(ref _opcUrl, value); }
        }
        private string _opcUrl;
        /// <summary>
        /// 用户选择变量的参数
        /// </summary>
        public string VariableValue
        {
            get { return _variableValue; }
            set { SetProperty(ref _variableValue, value); }
        }
        private string _variableValue;
        #endregion

        #region 事件绑定：刷新OPC通道
        /// <summary>
        /// 刷新OPC通道
        /// </summary>
        public ICommand RefreshOPC
        {
            get { return _refreshOPC; }
            set
            {
                _refreshOPC = value;
                OnPropertyChanged("RefreshOPC");
            }
        }
        private ICommand _refreshOPC;
        private void _RefreshOPC(object obj)
        {
            GetOpcList();
        }
        #endregion

        #region 事件：打开与关闭OPC连接，获取服务列表
        private OPCServer KepServer;
        private OPCBrowser KepBrower;
        private OPCGroups KepGroups;
        private OPCGroup KepGroup;
        private Array ServerHandles;
        private Array Errors;
        private int TransactionID = 0;
        private int CancelID = 0;
        /// <summary>
        /// OPC连接
        /// </summary>
        public void LinkOPC()
        {
            KepServer = new OPCServer();
            try
            {
                KepServer.Connect(NameSelected, OpcSelected);
                Tips tips = new Tips("OPC连接成功！");
                tips.Show();
                //获取所有变量
                KepBrower = KepServer.CreateBrowser();
                KepBrower.ShowBranches();
                KepBrower.ShowLeafs(true);
                Variable = new ObservableCollection<string>();
                foreach(var item in KepBrower)
                {
                    Variable.Add(item.ToString());
                }

                //通讯组集合初始化
                KepGroups = KepServer.OPCGroups;
                KepGroups.DefaultGroupDeadband = 0;
                KepGroups.DefaultGroupIsActive = true; ;

                //通信组初始化
                KepGroup = KepGroups.Add("CheemsOPC");
                KepGroup.IsActive= true;
                KepGroup.IsSubscribed = true;
                KepGroup.UpdateRate = 250;

                KepGroup.AsyncReadComplete += KepGroup_AsyncReadComplete;


                //异步读取
                int Count = Variable.Count;
                List<string> ItemIDS = new List<string>();
                List<int> ClientHandles = new List<int>();
                //初始化占位
                ItemIDS.Add("0");
                ClientHandles.Add(0);
                for (int i = 0; i < Count; i++)
                {
                    ItemIDS.Add(Variable[i]);
                    ClientHandles.Add(i + 1);
                }
                Array ItemID = ItemIDS.ToArray();
                Array ClientHandle = ClientHandles.ToArray();
                KepGroup.OPCItems.AddItems(Count, ref ItemID, ref ClientHandle, out ServerHandles, out Errors);
            }
            catch (Exception ex)
            {
                Tips tips = new Tips("OPC连接失败！\n" + ex.Message);
                tips.Show();
                OpcSwitch = false;
            }
            
        }

        /// <summary>
        /// 读取数据：调用KepGroup.AsyncRead后就会触发这个事件
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="ItemValues"></param>
        /// <param name="Qualities"></param>
        /// <param name="TimeStamps"></param>
        /// <param name="Errors"></param>
        private void KepGroup_AsyncReadComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errors)
        {
            //数据解析
            int Station = Variable.IndexOf(VariableSelected) + 1;
            VariableValue = ClientHandles.GetValue(Station).ToString();
        }

        public void CloseOPC()
        {

        }

        /// <summary>
        /// 获取节点，点界面刷新会触发该事件
        /// </summary>
        public void GetOpcList()
        {
            
            IPHostEntry iPHostEntry = Dns.GetHostEntry(Environment.MachineName);
            OpcSource = new ObservableCollection<string>();
            if (iPHostEntry.AddressList.Length > 0)
            {
                for (int i = 0; i < iPHostEntry.AddressList.Length; i++)
                {
                    string host = Dns.GetHostEntry(iPHostEntry.AddressList[i]).HostName;
                    if (!OpcSource.Contains(host))
                    {
                        OpcSource.Add(host);
                    }
                }
            }
            

        }
        /// <summary>
        /// 获取名称，用户选择节点后会触发该事件，获取该节点下的所有名称
        /// </summary>
        public void GetOpcNameList()
        {
            KepServer = new OPCServer();
            object nameList = KepServer.GetOPCServers(OpcSelected);
            OpcName = new ObservableCollection<string>();
            foreach (var item in (Array)nameList)
            {
                OpcName.Add(item.ToString());
            }
        }

        /// <summary>
        /// 输入OPC变量名，返回参数，用户在名称列表里选择一个变量时会触发该事件
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public string GetOpcData(string value)
        {
            string result = "";
            if (KepServer != null && Variable.Count > 0)
            {
                KepGroup.AsyncRead(Variable.Count, ref ServerHandles, out Errors, TransactionID, out CancelID);
            }
            return result;
        }

        #endregion
        
    }
}
